package com.itheima.test;

import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.IOUtils;
import org.junit.Test;

import java.io.*;
import java.util.List;
import java.util.zip.ZipInputStream;

public class ActivitiDemo {

    /**
     * 测试流程部署
     * act_re_deployment 流程部署表，每部署一次会增加一条记录
     * act_re_procdef 流程定义表
     * act_ge_bytearray 流程资源表
     */
    @Test
    public void testDeployment(){
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();

        //3、使用RepositoryService流程部署：把bpmn和png部署到数据库中，并给流程定义一个名字
        Deployment deployment = repositoryService.createDeployment()
                .name("出差申请流程")
                .addClasspathResource("bpmn/evection.bpmn20.xml")
                .addClasspathResource("bpmn/evection.png")
                .deploy();


        //4、输出部署的信息
        System.out.println("流程部署id="+deployment.getId());
        System.out.println("流程部署名字="+deployment.getName());
    }

    /**
     * 测试启动流程实例
     * act_hi_actinst：流程实例执行历史
     * act_hi_identitylink：流程参与用户信息历史
     * act_hi_procinst 流程实例历史信息
     * act_hi_taskinst 流程任务历史信息
     * act_ru_execution 流程正在执行信息
     * act_ru_identitylink：流程参与用户信息
     * act_ru_task：任务信息
     */
    @Test
    public void testStartProcess(){
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2、获取RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();

        //3、根据流程定义的id启动流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myEvection");

        //4、输出内容
        System.out.println("流程定义ID：" + processInstance.getProcessDefinitionId());
        System.out.println("流程实例ID：" + processInstance.getId());
        System.out.println("当前活动ID：" + processInstance.getActivityId());
    }

    /**
     * 查询个人待执行的任务
     */
    @Test
    public void testFindPersonTaskList(){
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();

        //3、根据流程的(key)的(任务的负责人) 来查询任务
        List<Task> taskList = taskService.createTaskQuery()
                .processDefinitionKey("myEvection") //流程key
                .taskAssignee("zhangsan")   //要查询的负责人
                .list();

        //4、输出
        for (Task task : taskList) {
            System.out.println("流程实例ID=" + task.getProcessInstanceId());
            System.out.println("任务ID=" + task.getId());
            System.out.println("任务负责人=" + task.getAssignee());
            System.out.println("任务名称=" + task.getName());
        }

    }

    @Test
    public void testCompleteZhangsanTask(){
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();

        //3、根据任务id完成任务，完成张三的任务
        taskService.complete("7505");
    }

    @Test
    public void testCompleteJerryTask(){
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();

        //3、查询jerry-myEvection任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("myEvection")
                .taskAssignee("jerry")
                .singleResult();
        System.out.println("流程实例ID=" + task.getProcessInstanceId());
        System.out.println("任务ID=" + task.getId());
        System.out.println("任务负责人=" + task.getAssignee());
        System.out.println("任务名称=" + task.getName());

        //4、完成任务
        taskService.complete(task.getId());
    }

    @Test
    public void testCompleteJackTask(){
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();

        //3、查询jack-myEvection任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("myEvection")
                .taskAssignee("jack")
                .singleResult();
        System.out.println("流程实例ID=" + task.getProcessInstanceId());
        System.out.println("任务ID=" + task.getId());
        System.out.println("任务负责人=" + task.getAssignee());
        System.out.println("任务名称=" + task.getName());

        //4、完成任务
        taskService.complete(task.getId());
    }

    @Test
    public void testCompleteRoseTask(){
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();

        //3、查询rose-myEvection任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("myEvection")
                .taskAssignee("rose")
                .singleResult();
        System.out.println("流程实例ID=" + task.getProcessInstanceId());
        System.out.println("任务ID=" + task.getId());
        System.out.println("任务负责人=" + task.getAssignee());
        System.out.println("任务名称=" + task.getName());

        //4、完成任务
        taskService.complete(task.getId());
    }

    /**
     * 使用zip包实现批量部署
     */
    @Test
    public void testDeployProcessByZip(){
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();

        //3、读取资源包文件，构造成InputStream
        InputStream inputStream = this.getClass()
                .getClassLoader()
                .getResourceAsStream("bpmn/evection.zip");

        //4、用InputStream构造ZipInputStream
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);

        //5、使用压缩包进行流程的部署
        Deployment deployment = repositoryService.createDeployment()
                .addZipInputStream(zipInputStream)
                .deploy();

        //6、输出部署的信息
        System.out.println("流程部署id="+deployment.getId());
        System.out.println("流程部署名字="+deployment.getName());

    }

    @Test
    public void queryProcessDefinition(){
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();

        //3、获取ProcessDefinition对象集合（流程定义信息集合）
        List<ProcessDefinition> processDefinitionList = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("myEvection")
                .orderByProcessDefinitionVersion()
                .desc()
                .list();

        //4、输出信息
        for (ProcessDefinition processDefinition : processDefinitionList) {
            System.out.println("流程定义ID = " + processDefinition.getId());//myEvection:1:4
            System.out.println("流程定义名称 = " + processDefinition.getName());//出差申请审批流
            System.out.println("流程定义key = " + processDefinition.getKey());//myEvection
            System.out.println("流程定义版本 = " + processDefinition.getVersion());//1
            System.out.println("流程部署id = " + processDefinition.getDeploymentId());//1
        }
    }

    /**
     * 删除流程部署信息
     */
    @Test
    public void deleteDeployment(){
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();

        //3、通过流程id删除流程部署信息
        String deploymentId = "1";
        repositoryService.deleteDeployment(deploymentId);
    }

    /**
     * 任务未执行完删除流程定义报错-但是还想要删除-级联删除
     */
    @Test
    public void cascadeDeleteDeployment(){
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();

        //3、通过流程id删除流程部署信息
        String deploymentId = "1";
        repositoryService.deleteDeployment(deploymentId,true);
    }

    /**
     * 资源下载
     * 方案1：使用Activiti提供的api，使用commons-io.jar保存到文件目录
     * 方案2：自己写代码操作数据库，需要使用jdbc读取blob类型数据，使用commons-io.jar保存到文件目录
     */
    @Test
    public void downloadDeployment() throws IOException {
        //1、得到流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();

        //3、获取流程定义
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("myEvection")
                .singleResult();

        //4、获取部署ID
        String deploymentId = processDefinition.getDeploymentId();

        //5、获取资源名称
        String pngName = processDefinition.getDiagramResourceName();
        String bpmnName = processDefinition.getResourceName();

        //5、根据部署ID读取资源信息（bpmn和png）
        InputStream pngInputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), pngName);
        InputStream bpmnInputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), bpmnName);

        //6、构造OutputStream
        File pngFile = new File("/Users/tianshengfei/Downloads/evectionflow01.png");
        File bpmnFile = new File("/Users/tianshengfei/Downloads/evectionflow01.bpmn");
        FileOutputStream pngOutputStream = new FileOutputStream(pngFile);
        FileOutputStream bpmnOutputStream = new FileOutputStream(bpmnFile);

        //7、输入流和输出流的转换
        IOUtils.copy(pngInputStream,pngOutputStream);
        IOUtils.copy(bpmnInputStream,bpmnOutputStream);

        //8、关闭流
        pngOutputStream.close();
        bpmnOutputStream.close();
        pngInputStream.close();
        bpmnInputStream.close();
    }

    /**
     * 查看历史信息
     */
    @Test
    public void queryHistoryInfo(){
        //1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2、获取HistoryService
        HistoryService historyService = processEngine.getHistoryService();

        //3、查询actinst表
        List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId("7501")
                .orderByHistoricActivityInstanceStartTime()
                .asc()
                .list();

        //4、输出
        for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
            System.out.println("historicActivityInstance.getActivityId() = " + historicActivityInstance.getActivityId());
            System.out.println("historicActivityInstance.getActivityName() = " + historicActivityInstance.getActivityName());
            System.out.println("historicActivityInstance.getProcessDefinitionId() = " + historicActivityInstance.getProcessDefinitionId());
            System.out.println("historicActivityInstance.getProcessInstanceId() = " + historicActivityInstance.getProcessInstanceId());
            System.out.println("================================");
        }
    }

}


